package com.flying.invest.assets.service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import com.flying.common.annotation.DaoCreate;
import com.flying.common.annotation.DaoQuery;
import com.flying.common.annotation.DaoRemove;
import com.flying.common.annotation.DaoUpdate;
import com.flying.common.annotation.Transaction;
import com.flying.common.util.Codes;
import com.flying.common.util.StringUtils;
import com.flying.common.util.Utils;
import com.flying.framework.annotation.MethodInfo;
import com.flying.framework.annotation.Param;
import com.flying.framework.annotation.Service;
import com.flying.framework.context.ServiceContext;
import com.flying.framework.model.ActionResult;
import com.flying.framework.model.ModelFactory;
import com.flying.framework.model.QueryResult;
import com.flying.framework.security.Principal;
import com.flying.framework.service.AbstractService;
import com.flying.invest.assets.RiskLevel;
import com.flying.invest.assets.model.Assets;
import com.flying.invest.assets.model.Assets.Status;
import com.flying.invest.assets.model.AssetsExt;
import com.flying.invest.assets.model.AssetsFavorite;
import com.flying.invest.assets.model.AssetsMarket;
import com.flying.invest.invest.service.InvestmentService;

@Service(value="AssetsService", desc="")
public class AssetsService extends AbstractService{
	private final static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
	private final Map<String, String> sortFields = Utils.newHashMap();
	
    private AssetsPriceService aps;
    private AssetsMarketService ams;
    private InvestmentService is;
    private AssetsPriceSpiderService apss;
    
    public void setAssetsPriceService(AssetsPriceService s) {
    	this.aps = s;
    }
    public void setAssetsMarketService(AssetsMarketService s) {
    	this.ams = s;
    }
    public void setInvestmentService(InvestmentService s) {
    	this.is = s;
    }
    public void setAssetsPriceSpiderService(AssetsPriceSpiderService s) {
    	this.apss = s;
    }
    
    public AssetsService() {
    	sortFields.put("blockName","block_id");
    	sortFields.put("marketName","market_id");
    	sortFields.put("assetsTypeName","type_id");

    	sortFields.put("fellRateM3","(max_price_m3 - price) / max_price_m3");
    	sortFields.put("riseRateM3","(price - min_price_m3) / min_price_m3");
    	sortFields.put("fellRateM6","(max_price_m6 - price) / max_price_m6");
    	sortFields.put("riseRateM6","(price - min_price_m6) / min_price_m6");
    	sortFields.put("fellRateM12","(max_price_m12 - price) / max_price_m12");
    	sortFields.put("riseRateM12","(price - min_price_m12) / min_price_m12");
    }
    
	@MethodInfo("新增")
	@DaoCreate(entity=Assets.ENTITY_NAME)
	public Assets create(
			@Param(value=Assets.TYPE_ID, required=true,	desc="类型ID") Long type_id,
			@Param(value=Assets.MARKET_ID, required=true,	desc="市场ID") Long market_id,
			@Param(value=Assets.BLOCK_ID, required=true,	desc="板块ID") Long block_id,
			@Param(value=Assets.NAME, required=true,	desc="名称") String name,
			@Param(value=Assets.CODE, required=false,	desc="代码") String code,
			@Param(value=Assets.INDUSTRY, required=false,	desc="行业") String industry,
			@Param(value=Assets.STATUS, required=false, enumClass=Status.class,	desc="状态") Integer status,
			
			@Param(value=Assets.PRICE, required=false,	desc="最新价格") Double price,
			@Param(value=Assets.UNIT, required=false,	desc="单位") String unit,
			@Param(value=Assets.TAX_RATE, required=false,	desc="交易税率") Double tax_rate,
			@Param(value=Assets.RISK_LEVEL, required=false, enumClass=RiskLevel.class,	desc="风险等级") Integer risk_level,
			@Param(value=Assets.REGION, required=false,	desc="所属区域（美国、欧洲等）") String region,
			@Param(value=Assets.REMARKS, required=false,	desc="说明") String remarks,
			@Param(value=Assets.SPIDER_SERVICE, required=false,	desc="爬虫服务") String spider_service,
			@Param(value=Assets.CURRENCY, required=false,	desc="币种") String currency,
			@Param(value=Assets.UPDATE_TIME, required=false,	desc="更新时间") Date update_time
		
		) throws Exception {
		if(currency == null) {
			AssetsMarket m = this.ams.findById(market_id);
			currency = m.getCurrency();
		}
		return ModelFactory.create(Assets.class, 
				Assets.CURRENCY, currency,
				Assets.UPDATE_TIME, new Date());
	}
	
	@MethodInfo("新增")
	public Assets create2(
			@Param(value=Assets.TYPE_ID, required=true,	desc="类型ID") Long type_id,
			@Param(value=Assets.MARKET_ID, required=true,	desc="市场ID") Long market_id,
			@Param(value=Assets.BLOCK_ID, required=true,	desc="板块ID") Long block_id,
			@Param(value=Assets.NAME, required=true,	desc="名称") String name,
			@Param(value=Assets.CODE, required=false,	desc="代码") String code,
			@Param(value=Assets.INDUSTRY, required=false,	desc="行业") String industry,
			@Param(value=Assets.STATUS, required=false, enumClass=Status.class,	desc="状态") Integer status,
			
			@Param(value=Assets.PRICE, required=false,	desc="最新价格") Double price,
			@Param(value=Assets.UNIT, required=false,	desc="单位") String unit,
			@Param(value=Assets.TAX_RATE, required=false,	desc="交易税率") Double tax_rate,
			@Param(value=Assets.RISK_LEVEL, required=false, enumClass=RiskLevel.class,	desc="风险等级") Integer risk_level,
			@Param(value=Assets.REGION, required=false,	desc="所属区域（美国、欧洲等）") String region,
			@Param(value=Assets.REMARKS, required=false,	desc="说明") String remarks,
			@Param(value=Assets.SPIDER_SERVICE, required=false,	desc="爬虫服务") String spider_service,
			@Param(value=Assets.CURRENCY, required=false,	desc="币种") String currency,
			@Param(value=Assets.UPDATE_TIME, required=false,	desc="更新时间") Date update_time
		
		) throws Exception {
		Assets a = this.create(type_id, market_id, block_id, name, code, industry, status, 
				price, unit, tax_rate, risk_level, region, remarks, spider_service, currency, update_time);
		if(!StringUtils.isEmpty(spider_service)) {
			this.apss.create2(a.getAssetsId(), spider_service);
		}
		return a;
	}

	@MethodInfo("修改")
	@Transaction
	@DaoUpdate(entity=Assets.ENTITY_NAME)
	public ActionResult update(
			@Param(value=Assets.ASSETS_ID, required=true,	desc="ASSETS ID") Long assets_id,
			@Param(value=Assets.TYPE_ID, required=false,	desc="类型ID") Long type_id,
			@Param(value=Assets.BLOCK_ID, required=true,	desc="板块ID") Long block_id,
			@Param(value=Assets.MARKET_ID, required=true,	desc="市场ID") Long market_id,
			@Param(value=Assets.NAME, required=false,	desc="名称") String name,
			@Param(value=Assets.CODE, required=false,	desc="代码") String code,
			@Param(value=Assets.INDUSTRY, required=false,	desc="行业") String industry,
			@Param(value=Assets.STATUS, required=false, enumClass=Status.class,	desc="状态") Integer status,
			@Param(value=Assets.PRICE, required=false,	desc="最新价格") Double price,
			@Param(value=Assets.UNIT, required=false,	desc="单位") String unit,
			@Param(value=Assets.TAX_RATE, required=false,	desc="交易税率") Double tax_rate,
			@Param(value=Assets.RISK_LEVEL, required=false, enumClass=RiskLevel.class,	desc="风险等级") Integer risk_level,
			@Param(value=Assets.REGION, required=false,	desc="所属区域（美国、欧洲等）") String region,
			@Param(value=Assets.REMARKS, required=false,	desc="说明") String remarks,
			@Param(value=Assets.CURRENCY, required=false,	desc="币种") String currency,
			@Param(value=Assets.SPIDER_SERVICE, required=false,	desc="爬虫服务") String spider_service,
			@Param(value=Assets.UPDATE_TIME, required=false,	desc="更新时间") Date update_time
		) throws Exception {
		if(price != null) {
			this.aps.updatePrice(assets_id, df.format(new Date()), price);
		}
		if(currency == null) {
			AssetsMarket m = this.ams.findById(market_id);
			currency = m.getCurrency();
		}
		this.apss.updateByAssetsId(assets_id, spider_service);
		return ModelFactory.create(ActionResult.class, 
				Assets.CURRENCY, currency,
				Assets.UPDATE_TIME, new Date());
	}

	@MethodInfo("修改价格")
	@Transaction
	@DaoUpdate(entity=Assets.ENTITY_NAME)
	public ActionResult updatePrice(
			@Param(value=Assets.ASSETS_ID, required=true,	desc="ASSETS ID") Long assets_id,
			@Param(value=Assets.PRICE, required=true,	desc="最新价格") Double price,
			@Param(value=Assets.PRICE_DATE, required=false,	desc="最新价格") Date price_date
		) throws Exception {
		if(price_date == null) price_date = new Date();
		this.is.updatePriceByAssetsId(assets_id, price);
		this.aps.updatePrice(assets_id, df.format(new Date()), price);
		return ModelFactory.create(ActionResult.class, Assets.PRICE_DATE, price_date);
	}

	@MethodInfo("修改价格")
	@DaoUpdate(entity=Assets.ENTITY_NAME)
	public ActionResult updateHistoryPrice(
			@Param(value=Assets.ASSETS_ID, required=true,	desc="ASSETS ID") Long assets_id,
			@Param(value=Assets.MAX_PRICE_M3, required=true,	desc="3个月最高价格") Double max_m3,
			@Param(value=Assets.MIN_PRICE_M3, required=true,	desc="3个月最低价格") Double min_m3,
			@Param(value=Assets.MAX_PRICE_M6, required=true,	desc="6个月最高价格") Double max_m6,
			@Param(value=Assets.MIN_PRICE_M6, required=true,	desc="6个月最低价格") Double min_m6,
			@Param(value=Assets.MAX_PRICE_M12, required=true,	desc="12个月最高价格") Double max_m12,
			@Param(value=Assets.MIN_PRICE_M12, required=true,	desc="12个月最低价格") Double min_m12
		) {
		return null;
	}

	@MethodInfo("删除")
	@DaoRemove(entity=Assets.ENTITY_NAME)
	public ActionResult remove(
			@Param(value=Assets.ASSETS_ID, required=true,	desc="ASSETS ID") Long assets_id
		) throws Exception {
		return null;
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索")
	@DaoQuery(entity=Assets.ENTITY_NAME, pageable=true, modelClass=AssetsExt.class,
			qsql="select t.*, (case when f.user_id is not null then 1 else 0 end) as favorited  "
					+ "from i_assets t left join i_assets_favorite f on t.assets_id=f.assets_id  and f.user_id =:user_id:")
	public QueryResult<AssetsExt> findAll(
			@Param(value=Assets.TYPE_ID, required=false,	desc="类型ID") Long type_id,
			@Param(value=Assets.MARKET_ID, required=false,	desc="市场ID") Long market_id,
			@Param(value=Assets.BLOCK_ID, required=false,	desc="板块ID") Long block_id,
			@Param(value=Assets.NAME, required=false,	desc="名称", tag="LIKE") String name,
			@Param(value=Assets.CODE, required=false,	desc="代码") String code,
			@Param(value=Assets.INDUSTRY, required=false,	desc="行业") String industry,
			@Param(value=Assets.RISK_LEVEL, required=false, enumClass=RiskLevel.class,	desc="风险等级") Integer risk_level,
			@Param(value=Assets.REGION, required=false,	desc="所属区域（美国、欧洲等）") String region,
			@Param(value=Assets.CURRENCY, required=false,	desc="币种") String currency,
			@Param(value="user_id", required=false,	desc="用户ID", tag="replace") Long user_id,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows,
			@Param(value=Codes.SORT, 	required=false, desc="排序字段") String sort,
			@Param(value=Codes.ORDER, 	required=false, desc="排序顺序") String order) {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null) user_id = Long.parseLong(p.getId());
		sort = sortFields.containsKey(sort)?sortFields.get(sort): sort;
		return ModelFactory.create(QueryResult.class, 
				"user_id", user_id,
				Codes.SORT, sort);
	}

	@MethodInfo("搜索")
	@DaoQuery(entity=Assets.ENTITY_NAME, pageable=true, modelClass=Assets.class)
	public QueryResult<Assets> findAll2(
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) {
		return null;
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索（完整），全搜索")
	@DaoQuery(entity=Assets.ENTITY_NAME, pageable=true, modelClass=AssetsExt.class, 
		qsql="select * from v_favorite_assets t", csql="select count(0) as c from v_favorite_assets t")
	public QueryResult<AssetsExt> findFavorites(
			@Param(value=AssetsFavorite.USER_ID, required=false,	desc="用户ID") Long user_id,
			@Param(value=Assets.TYPE_ID, required=false,	desc="类型ID") Long type_id,
			@Param(value=Assets.MARKET_ID, required=false,	desc="市场ID") Long market_id,
			@Param(value=Assets.BLOCK_ID, required=false,	desc="板块ID") Long block_id,
			@Param(value=Assets.NAME, required=false,	desc="名称", tag="LIKE") String name,
			@Param(value=Assets.CODE, required=false,	desc="代码") String code,
			@Param(value=Assets.INDUSTRY, required=false,	desc="行业") String industry,
			@Param(value=Assets.STATUS, required=false, enumClass=Status.class,	desc="状态") Integer status,
			@Param(value=Assets.RISK_LEVEL, required=false, enumClass=RiskLevel.class,	desc="风险等级") Integer risk_level,
			@Param(value=Assets.REGION, required=false,	desc="所属区域（美国、欧洲等）") String region,
			@Param(value=Assets.CURRENCY, required=false,	desc="币种") String currency,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows,
			@Param(value=Codes.SORT, 	required=false, desc="排序字段") String sort,
			@Param(value=Codes.ORDER, 	required=false, desc="排序顺序") String order) {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null) user_id = Long.parseLong(p.getId());
		sort = sortFields.containsKey(sort)?sortFields.get(sort): sort;
		return ModelFactory.create(QueryResult.class, 
				AssetsFavorite.USER_ID, user_id,
				Codes.SORT, sort);
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索（完整），用户关注的所有产品")
	@DaoQuery(entity=Assets.ENTITY_NAME, pageable=true, modelClass=Assets.class, 
		qsql="select * from v_favorite_assets t")
	public QueryResult<Assets> findAll3(
			@Param(value=AssetsFavorite.USER_ID, required=false,	desc="用户ID") Long user_id,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null) user_id = Long.parseLong(p.getId());
		return ModelFactory.create(QueryResult.class, 
				AssetsFavorite.USER_ID, user_id);
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索（简单），不包含加个变化产品")
	@DaoQuery(entity=Assets.ENTITY_NAME, pageable=true, modelClass=Assets.class, 
		qsql="select * from v_favorite_assets t", wsql="spider_service is not null", 
		csql="select count(0) as c from v_favorite_assets t")
	public QueryResult<Assets> findAll4(
			@Param(value=AssetsFavorite.USER_ID, required=false,	desc="用户ID") Long user_id,
			@Param(value=Assets.NAME, required=false,	desc="名称", tag="LIKE") String name,
			@Param(value=Assets.CODE, required=false,	desc="代码", tag="LIKE") String code,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows,
			@Param(value=Codes.SORT, 	required=false, desc="排序字段") String sort,
			@Param(value=Codes.ORDER, 	required=false, desc="排序顺序") String order) {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null) user_id = Long.parseLong(p.getId());
		sort = sortFields.containsKey(sort)?sortFields.get(sort): sort;
		return ModelFactory.create(QueryResult.class, 
				Codes.PAGE_SIZE, rows,
				Codes.SORT, sort,
				AssetsFavorite.USER_ID, user_id);
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索（简单），搜索用户关注的产品")
	@DaoQuery(entity=Assets.ENTITY_NAME, pageable=true, modelClass=Assets.class, 
		qsql="select * from v_favorite_assets t")
	public QueryResult<Assets> findAll5(
			@Param(value=AssetsFavorite.USER_ID, required=false,	desc="用户ID") Long user_id,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null) user_id = Long.parseLong(p.getId());
		return ModelFactory.create(QueryResult.class, 
				AssetsFavorite.USER_ID, user_id);
	}

	@MethodInfo("查询")
	@DaoQuery(entity=Assets.ENTITY_NAME, single=true, throwsNotFoundException=true )
	public Assets findById(
			@Param(value=Assets.ASSETS_ID, required=true,	desc="ASSETS ID") Long assets_id) {
		return null;
	}
	
	public Assets findByIdExt(
			@Param(value=Assets.ASSETS_ID, required=true,	desc="ASSETS ID") Long assets_id) {
		var assets = this.findById(assets_id);
		assets.put("wavem3", (assets.getMaxPriceM3() - assets.getMinPriceM3()) / assets.getMaxPriceM3() * 100);
		assets.put("wavem6", (assets.getMaxPriceM6() - assets.getMinPriceM6()) / assets.getMaxPriceM6() * 100);
		assets.put("wavem12", (assets.getMaxPriceM12() - assets.getMinPriceM12()) / assets.getMaxPriceM12() * 100);
		return assets;
	}

	@MethodInfo("查询")
	@DaoQuery(entity=Assets.ENTITY_NAME, single=true, throwsNotFoundException=true )
	public Assets findByCode(
			@Param(value=Assets.CODE, required=false,	desc="代码") String code ) {
		return null;
	}

	@MethodInfo("查询")
	@DaoQuery(entity=Assets.ENTITY_NAME, single=true, throwsNotFoundException=true )
	public Assets findById2(
			@Param(value=Assets.ASSETS_ID, required=true,	desc="ASSETS ID") Long assets_id
		) throws Exception {
		return null;
	}

}